from python_ai.common.xcommon import sep
import tensorflow as tf

sep('constant')
c1 = tf.constant(9.5, dtype=tf.float32)
c2 = tf.constant(10, dtype=tf.int32)
print(c1)
print(c2)

sep('variable')
a = tf.Variable(5.8)
b = tf.Variable(2.9)
sum = tf.Variable(0, name="sum")
result = tf.Variable(1, name="result")
print(a)
print(b)
print(sum)
print(result)

sep('f and f2')
f = tf.Variable([[2, 5, 4],
                 [1, 3, 6]], dtype=tf.float64)
f2 = tf.Variable([[2, 3],
                  [1, 2],
                  [3, 1]], dtype=tf.float64)
print(f)
print(f2)

sep('multiply')
vector1 = tf.constant([3, 3], dtype=tf.float64)
vector2 = tf.constant([1, 2], dtype=tf.float64)
result3 = tf.multiply(vector1, vector2)
result4 = tf.multiply(vector2, vector1)
print(result3)
print(result4)

sep('Session')
# The name tf.Session is deprecated. Please use tf.compat.v1.Session instead.
# sess = tf.Session()
sess = tf.compat.v1.Session()
# The name tf.global_variables_initializer is deprecated. Please use tf.compat.v1.global_variables_initializer instead.
# sess.run(tf.global_variables_initializer())
sess.run(tf.compat.v1.global_variables_initializer())
r3 = sess.run(result3)
r4 = sess.run(result4)
print(r3)
print(r4)

sep('+-*/')
print(f'+: {sess.run(tf.add(a, b))}')  # 5.8 + 2.9 = 8.7
print(f'-: {sess.run(tf.subtract(a, c1))}')  # 5.8 - 9.5 = -3.7
print(f'*: {sess.run(tf.multiply(a, b))}')  # 5.8 * 2.9 = 16.82
print(f'/: {sess.run(tf.divide(a, 2.0))}')  # 5.8 / 2.0 = 2.9

sep('Assign')
xceil = 100
for i in range(xceil + 1):
    # The name tf.assign is deprecated. Please use tf.compat.v1.assign instead.
    # sess.run(tf.assign(sum, tf.add(sum, i)))
    sess.run(tf.compat.v1.assign(sum, tf.add(sum, i)))
print(sum)
print(f'Add from 0 to {xceil}: {sess.run(sum)}')
xceil = 10
for i in range(1, xceil + 1):
    sess.run(tf.compat.v1.assign(result, tf.multiply(result, i)))
print(result)
print(f'Multiply from 1 to {xceil}: {sess.run(result)}')
sess.run(result.assign(2 * result))
print(f'2 * result = {sess.run(result)}')
sess.run(result.assign_add(1))
print(f'result += 1: {sess.run(result)}')

sep('Matrix calculations')
print(f'f: {sess.run(f)}')
print(f'f2: {sess.run(f2)}')
print(f'f.T: {sess.run(tf.transpose(f))}')
print(f'f@f2: {sess.run(tf.matmul(f, f2))}')

sep('argmax')
print(f'f: {sess.run(f)}')
print(f'f.argmax: {sess.run(tf.argmax(f))}')
print(f'f.argmax by rows: {sess.run(tf.argmax(f, axis=1))}')
print(f'f.argmax by cols: {sess.run(tf.argmax(f, axis=0))}')

sep('reduce sum')
print(f'f: {sess.run(f)}')
print(f'f.sum: {sess.run(tf.reduce_sum(f))}')
print(f'f.sum by rows: {sess.run(tf.reduce_sum(f, axis=1))}')
print(f'f.sum by cols: {sess.run(tf.reduce_sum(f, axis=0))}')

sep('reduce mean')
print(f'f: {sess.run(f)}')
print(f'f.mean: {sess.run(tf.reduce_mean(f))}')
print(f'f.mean by rows: {sess.run(tf.reduce_mean(f, axis=1))}')
print(f'f.mean by cols: {sess.run(tf.reduce_mean(f, axis=0))}')

sep('reduce max')
print(f'f: {sess.run(f)}')
print(f'f.max: {sess.run(tf.reduce_max(f))}')
print(f'f.max by rows: {sess.run(tf.reduce_max(f, axis=1))}')
print(f'f.max by cols: {sess.run(tf.reduce_max(f, axis=0))}')

sep('cast')
print(f'True=>int64: {sess.run(tf.cast(True, dtype=tf.int64))}')
print(f'True=>int64: {sess.run(tf.cast(True, dtype=tf.float64))}')
print(f'Int=>Float: {sess.run(tf.cast(1, dtype=tf.float64))}')
print(f'Float=>Int: {sess.run(tf.cast(1., dtype=tf.int64))}')
print(f'Float=>Int: {sess.run(tf.cast(1.23, dtype=tf.int64))}')

sep('compare')
print(f'Compare: {sess.run(tf.equal(c1, 9.5))}')
print(f'Compare: {sess.run(tf.equal(a, 5.8))}')
print(f'Compare: {sess.run(tf.equal(5.8, 5.8))}')
print(f'Compare: {sess.run(tf.equal(5.8, 5))}')
print(f'Compare: {sess.run(tf.equal(5., 5.8))}')
# print(f'Compare: {sess.run(tf.equal(5, 5.8))}')  # TypeError: Expected int32 passed to parameter 'y' of op 'Equal', got 5.8 of type 'float' instead. Error: Expected int32, got 5.8 of type 'float' instead.

# Finally close the session
sess.close()
